package team

import (
	"sanguo/cluster"
	"sanguo/node/common/transaction"
	"sanguo/node/node_team"
	"sanguo/node/node_team/com"
	"sanguo/rpc/teamToGameMsg"
	"time"

	cs_msg "sanguo/protocol/cs/message"
	ss_msg "sanguo/protocol/ss/message"
	ss_rpc "sanguo/protocol/ss/rpc"

	"github.com/golang/protobuf/proto"
	"github.com/sniperHW/kendynet"
)

const (
	Type_Join  = 1
	Type_Reply = 2
)

func onJoinTeamMsg(session kendynet.StreamSession, msg proto.Message) {

	arg := msg.(*ss_msg.JoinTeamMsg)
	node_team.Debugln("onJoinTeamMsg:", arg)

	if arg.GetMsgType() == ss_msg.JoinTeamMsgType_Join_Apply {

		_team := TeamMgr.GetTeam(arg.GetTeamID())

		toC := &cs_msg.JoinTeamToC{}
		if _team == nil {
			toC.TeamCode = cs_msg.TeamEnum(cs_msg.TeamEnum_NO_TEAM).Enum()
			com.SendToClient(cluster.PeerID(arg.GetGame()), arg.GetUserID(), toC)
		} else {
			if _team.Status == com.TeamStatus_Safe {
				if _team.AcceptApply == com.AcceptApply_AutoAgree {

					if _team.GetRoleCount() >= com.TeamMaxRoleCount {

						toC.TeamCode = cs_msg.TeamEnum(cs_msg.TeamEnum_MAXROLECOUNT).Enum()
						com.SendToClient(cluster.PeerID(arg.GetGame()), arg.GetUserID(), toC)
					} else {

						ToGameJionTeam(arg.GetUserID(), arg.GetRoleID(), cluster.PeerID(arg.GetGame()), _team, Type_Join)
					}
				} else if _team.AcceptApply == com.AcceptApply_AutoDisagree {

					toC.TeamCode = cs_msg.TeamEnum(cs_msg.TeamEnum_DISAGREE).Enum()
					com.SendToClient(cluster.PeerID(arg.GetGame()), arg.GetUserID(), toC)
				} else if _team.AcceptApply == com.AcceptApply_Request {

					_team.ApplyRoles[arg.GetRoleID()] = &ApplyRole{
						DestoryTime: time.Now().Unix() + com.ApplyMaxTime,
						UserID:      arg.GetUserID(),
						RoleID:      arg.GetRoleID(),
						Game:        cluster.PeerID(arg.GetGame()),
					}

					header := _team.GetRole(_team.Header)
					applyToC := &cs_msg.ApplyToC{
						UserID: proto.String(arg.GetUserID()),
						RoleID: proto.Uint64(arg.GetRoleID()),
						Name:   proto.String(arg.GetName()),
						Level:  proto.Int32(arg.GetLevel()),
					}

					header.SendToClient(applyToC)

				}
			} else if _team.Status == com.TeamStatus_Battle {
				toC.TeamCode = cs_msg.TeamEnum(cs_msg.TeamEnum_IN_BATTLE).Enum()
				com.SendToClient(cluster.PeerID(arg.GetGame()), arg.GetUserID(), toC)
			}
		}

	} else if arg.GetMsgType() == ss_msg.JoinTeamMsgType_Join_Reply {
		_team := TeamMgr.GetTeam(arg.GetTeamID())
		if _team != nil {

			applyRole := _team.ApplyRoles[arg.GetRoleID()]
			if applyRole != nil {
				if arg.GetAgreed() {
					if _team.GetRoleCount() < com.TeamMaxRoleCount {
						ToGameJionTeam(applyRole.UserID, applyRole.RoleID, applyRole.Game, _team, Type_Reply)
					}
				} else {
					toC := &cs_msg.JoinTeamToC{
						TeamCode: cs_msg.TeamEnum(cs_msg.TeamEnum_DISAGREE).Enum(),
					}

					com.SendToClient(applyRole.Game, applyRole.UserID, toC)
					delete(_team.ApplyRoles, applyRole.RoleID)
				}

			}

		}
	}
}

func ToGameJionTeam(userID string, roleID uint64, game cluster.PeerID, _team *Team, Type int) {
	toC := &cs_msg.JoinTeamToC{
		TeamCode: cs_msg.TeamEnum(cs_msg.TeamEnum_AGREED).Enum(),
	}
	req := &ss_rpc.TeamToGameMsgReq{
		MsgType: ss_rpc.TTGType(ss_rpc.TTGType_Join_Team).Enum(),
		UserID:  proto.String(userID),
		RoleID:  proto.Uint64(roleID),
		TeamID:  proto.Uint64(_team.TeamID),
	}

	teamToGameMsg.AsynCall(game, req, transaction.TransTimeoutMs, func(resp *ss_rpc.TeamToGameMsgResp, err error) {
		if nil == err && resp.GetOk() == 1 {
			node_team.Debugln("JoinTeam OK", _team.TeamID, userID)

			r := &Role{}
			r.RoleID = resp.GetRoleID()
			r.UserID = resp.GetUserID()
			r.Level = resp.GetLevel()
			r.Name = resp.GetName()
			r.Portrait = resp.GetPortrait()
			r.Outline = resp.GetOutline()
			r.Face = resp.GetFace()
			r.Hair = resp.GetHair()
			r.HairColor = resp.GetHairColor()
			r.EyeColor = resp.GetEyeColor()
			r.Cloth = resp.GetCloth()
			r.ClothColor = resp.GetClothColor()
			r.Weapon1 = resp.GetWeapon1()
			r.Game = cluster.PeerID(resp.GetGame())
			r.Status = com.RoleStatus_Online

			_team.AddRole(r)
			TeamMgr.RoleToTeam[r.RoleID] = _team

			r.SendToClient(toC)
			if Type == Type_Reply {
				delete(_team.ApplyRoles, roleID)
			}

			UpdateTeamToClients(_team)
		} else {
			node_team.Debugln("JoinTeam fail", resp, err)
			if Type == Type_Reply {
				delete(_team.ApplyRoles, roleID)

				replyToC := &cs_msg.ReplyJoinTeamToC{}
				if resp.GetRespType() == ss_rpc.TTGRespType_Off_Line {
					replyToC.TeamCode = cs_msg.TeamEnum(cs_msg.TeamEnum_OFF_LINE).Enum()
				} else if resp.GetRespType() == ss_rpc.TTGRespType_Join_Other_Team {
					replyToC.TeamCode = cs_msg.TeamEnum(cs_msg.TeamEnum_JOINOTHERTEAM).Enum()
				}
				header := _team.GetRole(_team.Header)
				header.SendToClient(replyToC)
			}
		}
	})
}

func init() {
	cluster.Register(&ss_msg.JoinTeamMsg{}, func(session kendynet.StreamSession, msg proto.Message) {
		onJoinTeamMsg(session, msg)
	})

}
